﻿using AutoMapper.Extensions.ExpressionMapping;
using BCCommon;
using BCCommon.Enums;
using BCCommon.NPinyin;
using BCService;
using BCWorkflowEngine;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using TMSWorkflowSpecificFormAutoJob.Redis;
using BCCommon.Extensions;
using BCService.TMS.Agent.AgentRecord;
using BCService.OA.WorkflowActivitySpecificFormExecuteRecord;
using BCDto.OA.WorkflowActive.WorkflowActivityStepSpecificFormItem;
using BCService.Sim.Company.Company;
using BCDto.TMS.Agent.AgentRecord;
using BCService.TMS.Agent.AgentAreaRecord;
using BCDto.OA.WorkflowActive.WorkflowActivitySpecificFormExecuteRecord;
using BCService.TMS.PlatformManageFee.PlatformManageFeeConfig;
using BCCommon.Enums.TMS;

namespace TMSWorkflowSpecificFormAutoJob
{
    class Program
    {
        public static IServiceCollection services { get; set; }
        public static IConfiguration configuration { get; set; }
        static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder();
#if DEBUG
            Console.WriteLine("DEBUG");
            builder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
#else
            Console.WriteLine("RELEASE");
            builder.AddJsonFile("/mnt/web/config/appsettings.production.json", optional: true, reloadOnChange: true);
#endif
            configuration = builder.Build();
            GeneralContainer.Configuration = configuration;
            services = new ServiceCollection()
                .AddLogging()
                .AddScoped<ILoggerFactory, LoggerFactory>()
                .AddMySql(option =>
                {
                    option.MasterConnectionString = configuration["MySqlConnectionString"];
                    option.SlaveConnectionString = configuration["MySqlConnectionString"];
                })
                .AddRedis(options =>
                {
                    if (bool.TryParse(configuration["EnableRedis"], out bool enableRedis))
                    {
                        options.EnableRedis = enableRedis;
                    }
                    options.RedisConnectionString = configuration["RedisConnectionString"];
                    options.RedisDatabaseNo = configuration["RedisDatabaseNo"];
                })
                .AddScoped<IApplicationContextService, ConsoleContextService>()
                .AddServices()
                .AddMapperConfiguration();

            #region 模型映射
            var mappingConfiguration = new AutoMapper.MapperConfiguration(cfg =>
            {
                cfg.AddMaps(Assembly.Load(new AssemblyName("BCService")));
                cfg.AddExpressionMapping();
            });
            mappingConfiguration.CompileMappings();
            BCService.Utils.MapperExtension.Mapper = mappingConfiguration.CreateMapper();

            var workflowConfiguration = new AutoMapper.MapperConfiguration(cfg =>
            {
                cfg.AddMaps(Assembly.Load(new AssemblyName("BCWorkflowEngine")));
                cfg.AddExpressionMapping();
            });
            workflowConfiguration.CompileMappings();

            BCWorkflowEngine.Utils.MapperExtension.Mapper = workflowConfiguration.CreateMapper();
            #endregion

            services.AddSingleton(typeof(IConfiguration), configuration);
            Console.WriteLine("Service Count:" + services.Count);
            IServiceProvider serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions().ValidateScopes);
            //ILoggerFactory loggerFactory = serviceProvider.GetService<ILoggerFactory>().AddConsole(LogLevel.Debug);
            //全局服务提供
            GeneralContainer.ServiceProvider = serviceProvider;
            TMSWorkflowStepSpecificFormExecution(serviceProvider);
        }

        private static void TMSWorkflowStepSpecificFormExecution(IServiceProvider serviceProvider)
        {
            Console.WriteLine("工作流步骤【特殊表单项】处理开始");
            IWorkflowEngine workflowEngine = serviceProvider.GetService<IWorkflowEngine>();
            IDatabaseContext databaseContext = serviceProvider.GetService<IDatabaseContext>();
            IAgentRecordService agentRecordService = serviceProvider.GetService<IAgentRecordService>();
            IWorkflowActivitySpecificFormExecuteRecordService specificFormExecuteRecordService = serviceProvider.GetService<IWorkflowActivitySpecificFormExecuteRecordService>();
            ICompanyService companyService = serviceProvider.GetService<ICompanyService>();
            IAgentAreaRecordService agentAreaRecordService = serviceProvider.GetService<IAgentAreaRecordService>();

            Console.WriteLine("构建工作流步骤【特殊表单项】处理服务完成");
            try
            {
                Console.WriteLine("开始调用处理程序");
                var workflowActivity = workflowEngine.GetWorkflowActivityStepSpecificFormDone();
                if (workflowActivity.Any() && workflowActivity.FirstOrDefault().Key > 0)
                {
                    var workflowActivityId = workflowActivity.FirstOrDefault().Key;
                    var specificTemplateKey = workflowActivity.FirstOrDefault().Value;
                    var activityStepSpecificFormItemList = workflowEngine.GetActivityStepSpecificFormItemList(workflowActivityId);
                    if (activityStepSpecificFormItemList.Any(p => p.IsExecution == false))
                    {
                        var specificFormExecuteRecordList = specificFormExecuteRecordService.GetByWorkflowActivityId(workflowActivityId);

                        Dictionary<string, string> keyValuePairs = new();
                        if (specificTemplateKey == "WT_CreateCompanyAgentInfo")
                        {
                            CreateCompanyAgentInfo(workflowEngine, databaseContext, agentRecordService, specificFormExecuteRecordService, companyService, agentAreaRecordService, workflowActivityId, activityStepSpecificFormItemList, specificFormExecuteRecordList, keyValuePairs);
                        }
                        else if (specificTemplateKey == "WT_ModifyAgentInfo")
                        {
                            IPlatformManageFeeConfigService platformManageFeeConfigService = serviceProvider.GetService<IPlatformManageFeeConfigService>();
                            ModifyAgentInfo(workflowEngine, databaseContext, agentRecordService, specificFormExecuteRecordService, platformManageFeeConfigService, workflowActivityId, activityStepSpecificFormItemList, specificFormExecuteRecordList, keyValuePairs);
                        }
                    }
                    else
                    {
                        workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                    }
                }
                Console.WriteLine("完成");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Log(JsonConvert.SerializeObject(ex));
            }
        }

        private static void ModifyAgentInfo(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, IAgentRecordService agentRecordService, IWorkflowActivitySpecificFormExecuteRecordService specificFormExecuteRecordService, IPlatformManageFeeConfigService platformManageFeeConfigService, long workflowActivityId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> activityStepSpecificFormItemList, IEnumerable<WorkflowActivitySpecificFormExecuteRecordDto> specificFormExecuteRecordList, Dictionary<string, string> keyValuePairs)
        {
            long agentRecordId = 0;
            var tableName = "AgentRecord";
            Dictionary<string, string> updateKeyValuePairs = new Dictionary<string, string>();
            var agentInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == tableName);
            if (agentInfoList != null && agentInfoList.Any())
            {
                if (!specificFormExecuteRecordList.Any(p => p.FormTable == tableName))
                {
                    var agentRecord = agentRecordService.Get(Convert.ToInt64(agentInfoList.FirstOrDefault(p => p.BoundField == "AgentRecordId").ItemValue));
                    if (agentRecord != null)
                    {
                        agentRecordId = agentRecord.AgentRecordId;
                        var parentAgentRecord = agentRecordService.GetByCompanyId(agentRecord.ParentCompanyId);
                        (keyValuePairs, updateKeyValuePairs) = GetUpdateAgentRcordInfo(agentInfoList, agentRecord, parentAgentRecord);
                        databaseContext.BeginTransaction();
                        workflowEngine.UpdateSpecificFormTable(tableName, keyValuePairs, updateKeyValuePairs);
                        workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, null, null);
                        specificFormExecuteRecordService.Insert(new BCDto.OA.WorkflowActive.WorkflowActivitySpecificFormExecuteRecord.WorkflowActivitySpecificFormExecuteRecordDto()
                        {
                            WorkflowActivityId = workflowActivityId,
                            FormTable = tableName,
                            BoundField = "AgentRecordId",
                            BoundFieldValue = agentRecord.AgentRecordId.ToString(),
                            CreateTime = DateTime.Now
                        });
                        databaseContext.Commit();
                    }
                }
            }
            tableName = "PlatformManageFeeConfig";
            var platformManageFeeInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == tableName);
            if (platformManageFeeInfoList != null && platformManageFeeInfoList.Any())
            {
                if (!specificFormExecuteRecordList.Any(p => p.FormTable == tableName))
                {
                    var platformManageFeeConfig = platformManageFeeConfigService.GetById(Convert.ToInt64(platformManageFeeInfoList.FirstOrDefault(p => p.BoundField == "PlatformManageFeeConfigId").ItemValue));
                    if (platformManageFeeConfig != null)
                    {
                        tableName = "PlatformManageFeeExecutionPlan";
                        agentRecordId = platformManageFeeConfig.SubAgentRecordId;
                        var agentRecord = agentRecordService.Get(agentRecordId);
                        if (agentRecord != null)
                        {
                            var parentAgentRecord = agentRecordService.GetByCompanyId(agentRecord.ParentCompanyId);
                            keyValuePairs = GetPlatformManageFeeConfigInfo(platformManageFeeInfoList, platformManageFeeConfig, parentAgentRecord);
                        }
                        else
                        {
                            keyValuePairs = GetPlatformManageFeeConfigInfo(platformManageFeeInfoList, platformManageFeeConfig, null);
                        }
                        databaseContext.BeginTransaction();
                        var platformManageFeeExecutionPlanId = workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                        if (Convert.ToBoolean(keyValuePairs["IsDone"]) && platformManageFeeExecutionPlanId > 0)
                        {
                            Dictionary<string, string> tempKeyValuePairs = new Dictionary<string, string>();
                            updateKeyValuePairs = new Dictionary<string, string>();
                            updateKeyValuePairs.TryAdd("PlatformManageFeeConfigId", platformManageFeeConfig.PlatformManageFeeConfigId.ToString());
                            tempKeyValuePairs.TryAdd("AgentRecordId", keyValuePairs["AgentRecordId"]);
                            tempKeyValuePairs.TryAdd("CompanyId", keyValuePairs["CompanyId"]);
                            tempKeyValuePairs.TryAdd("CurrentlyPlatformManageFeeExecutionPlanId", platformManageFeeExecutionPlanId.ToString());
                            tempKeyValuePairs.TryAdd("ManageFeeRatio", keyValuePairs["ManageFeeRatio"]);
                            workflowEngine.UpdateSpecificFormTable("PlatformManageFeeConfig", tempKeyValuePairs, updateKeyValuePairs);
                        }
                        workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, "PlatformManageFeeConfig", null, null);
                        specificFormExecuteRecordService.Insert(new BCDto.OA.WorkflowActive.WorkflowActivitySpecificFormExecuteRecord.WorkflowActivitySpecificFormExecuteRecordDto()
                        {
                            WorkflowActivityId = workflowActivityId,
                            FormTable = "PlatformManageFeeConfig",
                            BoundField = "SubAgentRecordId",
                            BoundFieldValue = platformManageFeeConfig.SubAgentRecordId.ToString(),
                            CreateTime = DateTime.Now
                        });
                        databaseContext.Commit();
                    }
                }
            }
            if (agentRecordId > 0)
            {
                if (specificFormExecuteRecordList.Any(p => p.FormTable == "AgentRecord") || specificFormExecuteRecordList.Any(p => p.FormTable == "PlatformManageFeeConfig"))
                {
                    InsertProtocol(workflowEngine, databaseContext, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                    workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                }
            }
            else
            {
                if (specificFormExecuteRecordList.Any(p => p.FormTable == "AgentRecord"))
                {
                    agentRecordId = Convert.ToInt64(specificFormExecuteRecordList.FirstOrDefault(p => p.FormTable == "AgentRecord").BoundFieldValue);
                }
                else if (specificFormExecuteRecordList.Any(p => p.FormTable == "PlatformManageFeeConfig"))
                {
                    agentRecordId = Convert.ToInt64(specificFormExecuteRecordList.FirstOrDefault(p => p.FormTable == "PlatformManageFeeConfig").BoundFieldValue);
                }
                if (agentRecordId > 0)
                {
                    InsertProtocol(workflowEngine, databaseContext, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                    workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                }
            }
        }

        private static Dictionary<string, string> GetPlatformManageFeeConfigInfo(IEnumerable<WorkflowActivityStepSpecificFormItemDto> platformManageFeeInfoList, BCDto.TMS.PlatformManageFee.PlatformManageFeeConfig.PlatformManageFeeConfigDto platformManageFeeConfig, AgentRecordDto parentAgentRecord)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var item in platformManageFeeInfoList)
            {
                keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            keyValuePairs.Remove("PlatformManageFeeConfigId");
            var editerId = platformManageFeeInfoList.FirstOrDefault().CreateAdminId;
            var editer = platformManageFeeInfoList.FirstOrDefault().CreateAdminName;
            keyValuePairs.TryAdd("AgentRecordId", parentAgentRecord?.AgentRecordId.ToString());
            keyValuePairs.TryAdd("CompanyId", parentAgentRecord?.CompanyId.ToString());
            keyValuePairs.TryAdd("SubAgentRecordId", platformManageFeeConfig.SubAgentRecordId.ToString());
            keyValuePairs.TryAdd("ManageFeeBusinessType", platformManageFeeConfig.ManageFeeBusinessType);
            keyValuePairs.TryAdd("ExecutionType", DateTime.Today.Day == 1 ? ExecutionType.Now.ToString() : ExecutionType.Date.ToString());
            keyValuePairs.TryAdd("IsDone", DateTime.Today.Day == 1 ? "1": "0");
            keyValuePairs.TryAdd("CreateTime", DateTime.Now.ToString());
            keyValuePairs.TryAdd("CreateAdminId", editerId.ToString());
            keyValuePairs.TryAdd("CreateAdminName", editer);
            return keyValuePairs;
        }

        private static (Dictionary<string, string>, Dictionary<string, string>) GetUpdateAgentRcordInfo(IEnumerable<WorkflowActivityStepSpecificFormItemDto> agentInfoList, AgentRecordDto agentRecord, AgentRecordDto parentAgentRecord)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            Dictionary<string, string> updateKeyValuePairs = new Dictionary<string, string>();
            foreach (var item in agentInfoList)
            {
                if (item.BoundField == "AgentRecordId")
                    updateKeyValuePairs.TryAdd(item.BoundField, item.ItemValue);
                else
                    keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            var editerId = agentInfoList.FirstOrDefault().CreateAdminId;
            var editer = agentInfoList.FirstOrDefault().CreateAdminName;
            keyValuePairs.TryAdd("CompanyPathCode", parentAgentRecord == null ? $"{agentRecord.ParentCompanyId},{agentRecord.CompanyId}" : $"{parentAgentRecord.CompanyPathCode},{agentRecord.CompanyId}");
            keyValuePairs.TryAdd("UpdateTime", DateTime.Now.ToString());
            keyValuePairs.TryAdd("EditAdminId", editerId.ToString());
            keyValuePairs.TryAdd("EditAdminName", editer);
            return (keyValuePairs, updateKeyValuePairs);
        }

        private static void CreateCompanyAgentInfo(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, IAgentRecordService agentRecordService, IWorkflowActivitySpecificFormExecuteRecordService specificFormExecuteRecordService, ICompanyService companyService, IAgentAreaRecordService agentAreaRecordService, long workflowActivityId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> activityStepSpecificFormItemList, IEnumerable<WorkflowActivitySpecificFormExecuteRecordDto> specificFormExecuteRecordList, Dictionary<string, string> keyValuePairs)
        {
            var tableName = "Company";
            if (!specificFormExecuteRecordList.Any(p => p.FormTable == tableName))
            {
                var companyInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == tableName).ToList();
                if (companyInfoList.Any() && companyInfoList.Any(p => p.IsExecution == false))
                {
                    var companyName = companyInfoList.Where(p => p.BoundField == "CompanyName").FirstOrDefault().ItemValue;
                    var editerId = companyInfoList.FirstOrDefault().CreateAdminId;
                    var editer = companyInfoList.FirstOrDefault().CreateAdminName;
                    keyValuePairs = GetCompanyInfo(companyInfoList, companyName, editerId, editer);
                    databaseContext.BeginTransaction();
                    var companyId = workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                    workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, null, null);
                    specificFormExecuteRecordService.Insert(new BCDto.OA.WorkflowActive.WorkflowActivitySpecificFormExecuteRecord.WorkflowActivitySpecificFormExecuteRecordDto()
                    {
                        WorkflowActivityId = workflowActivityId,
                        FormTable = tableName,
                        BoundField = "CompanyId",
                        BoundFieldValue = companyId.ToString(),
                        CreateTime = DateTime.Now
                    });
                    databaseContext.Commit();
                    if (companyId > 0)
                    {
                        InsertAdminInfo(workflowEngine, databaseContext, specificFormExecuteRecordService, companyService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, ref tableName, companyInfoList, companyId);
                        var agentInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == "AgentRecord");
                        if (agentInfoList.Any())
                        {
                            var parentCompanyId = agentInfoList.FirstOrDefault(p => p.BoundField == "ParentCompanyId").ItemValue;
                            var agentRecord = agentRecordService.GetByCompanyId(Convert.ToInt32(parentCompanyId));
                            long agentRecordId = InsertAgentInfo(workflowEngine, databaseContext, specificFormExecuteRecordService, workflowActivityId, out keyValuePairs, out tableName, companyId, agentInfoList, parentCompanyId, agentRecord);
                            if (agentRecordId > 0)
                            {
                                InsertProtocol(workflowEngine, databaseContext, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                                InsertAgentAreaInfo(workflowEngine, databaseContext, agentAreaRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                                InsertPlatformManageFeeConfig(workflowEngine, databaseContext, agentRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId, companyId);
                                workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                            }
                        }
                    }
                }
            }
            else if (!specificFormExecuteRecordList.Any(p => p.FormTable == "Admin"))
            {
                var companyId = specificFormExecuteRecordList.FirstOrDefault(p => p.BoundField == "CompanyId").BoundFieldValue;
                InsertAdminInfo(workflowEngine, databaseContext, specificFormExecuteRecordService, companyService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, ref tableName, activityStepSpecificFormItemList.Where(p => p.FormTable == "Company"), Convert.ToInt64(companyId));
                var agentInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == "AgentRecord");
                if (agentInfoList.Any())
                {
                    var parentCompanyId = agentInfoList.FirstOrDefault(p => p.BoundField == "ParentCompanyId").ItemValue;
                    var agentRecord = agentRecordService.GetByCompanyId(Convert.ToInt32(parentCompanyId));
                    long agentRecordId = InsertAgentInfo(workflowEngine, databaseContext, specificFormExecuteRecordService, workflowActivityId, out keyValuePairs, out tableName, Convert.ToInt64(companyId), agentInfoList, parentCompanyId, agentRecord);
                    if (agentRecordId > 0)
                    {
                        InsertProtocol(workflowEngine, databaseContext, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                        InsertAgentAreaInfo(workflowEngine, databaseContext, agentAreaRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                        InsertPlatformManageFeeConfig(workflowEngine, databaseContext, agentRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId, Convert.ToInt64(companyId));
                        workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                    }
                }
            }
            else if (!specificFormExecuteRecordList.Any(p => p.FormTable == "AgentRecord"))
            {
                var companyId = specificFormExecuteRecordList.FirstOrDefault(p => p.BoundField == "CompanyId").BoundFieldValue;
                var agentInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == "AgentRecord");
                if (agentInfoList.Any())
                {
                    var parentCompanyId = agentInfoList.FirstOrDefault(p => p.BoundField == "ParentCompanyId").ItemValue;
                    var agentRecord = agentRecordService.GetByCompanyId(Convert.ToInt32(parentCompanyId));
                    long agentRecordId = InsertAgentInfo(workflowEngine, databaseContext, specificFormExecuteRecordService, workflowActivityId, out keyValuePairs, out tableName, Convert.ToInt64(companyId), agentInfoList, parentCompanyId, agentRecord);
                    if (agentRecordId > 0)
                    {
                        InsertProtocol(workflowEngine, databaseContext, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                        InsertAgentAreaInfo(workflowEngine, databaseContext, agentAreaRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                        InsertPlatformManageFeeConfig(workflowEngine, databaseContext, agentRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId, Convert.ToInt64(companyId));
                        workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                    }
                }
            }
            else
            {
                var agentRecordId = Convert.ToInt64(specificFormExecuteRecordList.FirstOrDefault(p => p.BoundField == "AgentRecordId").BoundFieldValue);
                if (agentRecordId > 0)
                {
                    InsertProtocol(workflowEngine, databaseContext, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                    InsertAgentAreaInfo(workflowEngine, databaseContext, agentAreaRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId);
                    var companyId = specificFormExecuteRecordList.FirstOrDefault(p => p.BoundField == "CompanyId").BoundFieldValue;
                    InsertPlatformManageFeeConfig(workflowEngine, databaseContext, agentRecordService, workflowActivityId, activityStepSpecificFormItemList, ref keyValuePairs, agentRecordId, Convert.ToInt64(companyId));
                    workflowEngine.UpdateActivityStatusToDone(workflowActivityId);
                }
            }
        }

        private static void InsertPlatformManageFeeConfig(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, IAgentRecordService agentRecordService, long workflowActivityId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> activityStepSpecificFormItemList, ref Dictionary<string, string> keyValuePairs, long agentRecordId, long companyId)
        {
            string tableName = "PlatformManageFeeConfig";
            if (activityStepSpecificFormItemList.Any(p => p.FormTable == tableName && p.IsExecution == false))
            {
                var agentRecord = agentRecordService.Get(agentRecordId);
                AgentRecordDto parentAgentRecord = null;
                if (agentRecord != null)
                {
                    parentAgentRecord = agentRecordService.GetByCompanyId(agentRecord.ParentCompanyId);
                }

                keyValuePairs = new Dictionary<string, string>();
                keyValuePairs.TryAdd("ManageFeeBusinessType", activityStepSpecificFormItemList.FirstOrDefault(p => p.FormTable == tableName && p.IsExecution == false && p.BoundField == "ManageFeeBusinessType").ItemValue);
                keyValuePairs.TryAdd("ManageFeeRatio", activityStepSpecificFormItemList.FirstOrDefault(p => p.FormTable == tableName && p.IsExecution == false && p.BoundField == "ManageFeeRatio").ItemValue);

                if (parentAgentRecord != null)
                {
                    keyValuePairs.TryAdd("AgentRecordId", parentAgentRecord.AgentRecordId.ToString());
                    keyValuePairs.TryAdd("CompanyId", parentAgentRecord.CompanyId.ToString());
                }
                keyValuePairs.TryAdd("SubAgentRecordId", agentRecordId.ToString());
                keyValuePairs.TryAdd("SubCompanyId", companyId.ToString());
                keyValuePairs.TryAdd("CreateAdminId", agentRecord.CreateAdminId.ToString());
                keyValuePairs.TryAdd("CreateAdminName", agentRecord.CreateAdminName);

                databaseContext.BeginTransaction();
                workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, null, null);
                databaseContext.Commit();
            }
        }

        private static long InsertAgentInfo(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, IWorkflowActivitySpecificFormExecuteRecordService specificFormExecuteRecordService, long workflowActivityId, out Dictionary<string, string> keyValuePairs, out string tableName, long companyId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> agentInfoList, string parentCompanyId, BCDto.TMS.Agent.AgentRecord.AgentRecordDto agentRecord)
        {
            tableName = "AgentRecord";
            keyValuePairs = GetAgentRcordInfo(companyId, agentInfoList, parentCompanyId, agentRecord);
            databaseContext.BeginTransaction();
            var agentRecordId = workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
            workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, null, null);
            specificFormExecuteRecordService.Insert(new BCDto.OA.WorkflowActive.WorkflowActivitySpecificFormExecuteRecord.WorkflowActivitySpecificFormExecuteRecordDto()
            {
                WorkflowActivityId = workflowActivityId,
                FormTable = tableName,
                BoundField = "AgentRecordId",
                BoundFieldValue = agentRecordId.ToString(),
                CreateTime = DateTime.Now
            });
            databaseContext.Commit();
            return agentRecordId;
        }

        private static void InsertProtocol(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, long workflowActivityId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> activityStepSpecificFormItemList, ref Dictionary<string, string> keyValuePairs, long agentRecordId)
        {
            string tableName = "AgentCurrentlyProtocol";
            var agentCurrentlyProtocolInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == tableName && p.IsExecution == false);
            if (agentCurrentlyProtocolInfoList != null && agentCurrentlyProtocolInfoList.Any())
            {
                foreach (var configRows in agentCurrentlyProtocolInfoList.Select(p => p.FormConfigRows).Distinct())
                {
                    var tempCurrentlyProtocolList = agentCurrentlyProtocolInfoList.Where(p => p.FormConfigRows == configRows);
                    keyValuePairs = GetCurrentlyProtocol(agentRecordId, tempCurrentlyProtocolList);
                    databaseContext.BeginTransaction();
                    var agentCurrentlyProtocolId = workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                    workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, configRows, null);
                    tableName = "AgentCurrentlyProtocolAttachment";
                    var protocolAttachmentList = activityStepSpecificFormItemList.Where(p => p.FormTable == tableName && p.FormConfigRows == configRows && p.IsExecution == false);

                    foreach (var formItemRows in protocolAttachmentList.Select(p => p.FormItemRows).Distinct())
                    {
                        keyValuePairs = GetProtocolAttachment(agentCurrentlyProtocolId, protocolAttachmentList, formItemRows);
                        workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                        workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, configRows, formItemRows);
                    }
                    databaseContext.Commit();
                }
            }
        }

        private static void InsertAgentAreaInfo(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, IAgentAreaRecordService agentAreaRecordService, long workflowActivityId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> activityStepSpecificFormItemList, ref Dictionary<string, string> keyValuePairs, long agentRecordId)
        {
            string tableName = "AgentAreaRecord";
            var agentAreaInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == tableName && p.IsExecution == false);
            if (agentAreaInfoList != null && agentAreaInfoList.Any())
            {
                foreach (var configRows in agentAreaInfoList.Select(p => p.FormConfigRows).Distinct())
                {
                    var tempAgentAreaInfoList = agentAreaInfoList.Where(p => p.FormConfigRows == configRows);
                    keyValuePairs = GetAreaRecordInfo(agentRecordId, tempAgentAreaInfoList);
                    databaseContext.BeginTransaction();
                    var agentAreaRecordId = workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                    workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, configRows, null);
                    agentAreaRecordService.UpdateIsChildAgent(agentAreaRecordId, keyValuePairs.GetValueOrDefault("CountyCode"));
                    databaseContext.Commit();
                }
            }
        }

        private static void InsertAdminInfo(IWorkflowEngine workflowEngine, IDatabaseContext databaseContext, IWorkflowActivitySpecificFormExecuteRecordService specificFormExecuteRecordService, ICompanyService companyService, long workflowActivityId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> activityStepSpecificFormItemList, ref Dictionary<string, string> keyValuePairs, ref string tableName, IEnumerable<WorkflowActivityStepSpecificFormItemDto> companyInfoList, long companyId)
        {
            tableName = "Admin";
            var adminInfoList = activityStepSpecificFormItemList.Where(p => p.FormTable == "Admin");
            if (adminInfoList.Any(p => p.IsExecution == false))
            {
                keyValuePairs = GetAdminInfo(companyInfoList, companyId, adminInfoList);
                databaseContext.BeginTransaction();
                var adminId = workflowEngine.InsertSpecificFormTable(tableName, keyValuePairs);
                workflowEngine.UpdateSpecificFormIsExecution(workflowActivityId, tableName, null, null);
                specificFormExecuteRecordService.Insert(new BCDto.OA.WorkflowActive.WorkflowActivitySpecificFormExecuteRecord.WorkflowActivitySpecificFormExecuteRecordDto()
                {
                    WorkflowActivityId = workflowActivityId,
                    FormTable = tableName,
                    BoundField = "AdminId",
                    BoundFieldValue = adminId.ToString(),
                    CreateTime = DateTime.Now
                });
                companyService.UpdateCompanyAdminId(companyId, adminId);
                companyService.JobAdd(adminId);
                databaseContext.Commit();
            }
        }

        private static Dictionary<string, string> GetAreaRecordInfo(long agentRecordId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> tempAgentAreaInfoList)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var item in tempAgentAreaInfoList)
            {
                keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            var editerId = tempAgentAreaInfoList.FirstOrDefault().CreateAdminId;
            var editer = tempAgentAreaInfoList.FirstOrDefault().CreateAdminName;
            keyValuePairs.Remove("AgentRecordId");
            keyValuePairs.TryAdd("AgentRecordId", agentRecordId.ToString());
            keyValuePairs.TryAdd("CreateAdminId", editerId.ToString());
            keyValuePairs.TryAdd("CreateAdminName", editer);
            keyValuePairs.TryAdd("UpdateTime", DateTime.Now.ToString());
            keyValuePairs.TryAdd("EditAdminId", editerId.ToString());
            keyValuePairs.TryAdd("EditAdminName", editer);
            return keyValuePairs;
        }

        private static Dictionary<string, string> GetProtocolAttachment(long agentCurrentlyProtocolId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> protocolAttachmentList, int? formItemRows)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var attachment in protocolAttachmentList.Where(p => p.FormItemRows == formItemRows))
            {
                keyValuePairs.TryAdd(attachment.BoundField, attachment.ItemValue);
            }
            keyValuePairs.TryAdd("AgentCurrentlyProtocolId", agentCurrentlyProtocolId.ToString());
            keyValuePairs.TryAdd("CreateTime", DateTime.Now.ToString());
            return keyValuePairs;
        }

        private static Dictionary<string, string> GetCurrentlyProtocol(long agentRecordId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> tempCurrentlyProtocolList)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var item in tempCurrentlyProtocolList)
            {
                keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            keyValuePairs.TryAdd("AgentRecordId", agentRecordId.ToString());
            keyValuePairs.TryAdd("CreateTime", DateTime.Now.ToString());
            return keyValuePairs;
        }

        private static Dictionary<string, string> GetAgentRcordInfo(long companyId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> agentInfoList, string parentCompanyId, BCDto.TMS.Agent.AgentRecord.AgentRecordDto agentRecord)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var item in agentInfoList)
            {
                keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            var editerId = agentInfoList.FirstOrDefault().CreateAdminId;
            var editer = agentInfoList.FirstOrDefault().CreateAdminName;
            keyValuePairs.TryAdd("CompanyId", companyId.ToString());
            keyValuePairs.TryAdd("CompanyPathCode", agentRecord == null ? $"{parentCompanyId},{companyId}" : $"{agentRecord.CompanyPathCode},{companyId}");
            keyValuePairs.TryAdd("CreateAdminId", editerId.ToString());
            keyValuePairs.TryAdd("CreateAdminName", editer);
            keyValuePairs.TryAdd("UpdateTime", DateTime.Now.ToString());
            keyValuePairs.TryAdd("EditAdminId", editerId.ToString());
            keyValuePairs.TryAdd("EditAdminName", editer);
            keyValuePairs.TryAdd("AgentRecordUuid", Guid.NewGuid().ToString());
            return keyValuePairs;
        }

        private static Dictionary<string, string> GetAdminInfo(IEnumerable<WorkflowActivityStepSpecificFormItemDto> companyInfoList, long companyId, IEnumerable<WorkflowActivityStepSpecificFormItemDto> adminInfoList)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var item in adminInfoList)
            {
                keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            var companyName = companyInfoList.FirstOrDefault(p => p.BoundField == "CompanyName").ItemValue;
            var fullName = companyInfoList.FirstOrDefault(p => p.BoundField == "CompanyAdminName").ItemValue;
            var loginName = Pinyin.GetCompactPinyin(fullName);
            keyValuePairs.TryAdd("LoginName", loginName);
            keyValuePairs.TryAdd("Password", "test0011".SHA256(loginName));
            keyValuePairs.TryAdd("FullName", fullName);
            keyValuePairs.TryAdd("CompanyId", companyId.ToString());
            keyValuePairs.TryAdd("CompanyName", companyName);
            keyValuePairs.TryAdd("LogonIp", "192.168.1.1");
            keyValuePairs.TryAdd("AddressIp", "局域网");
            keyValuePairs.TryAdd("AccountStatus", AccountStatus.Using.ToString());
            keyValuePairs.TryAdd("HomeAddress", companyName);
            keyValuePairs.TryAdd("Sex", Sex.Man.ToString());
            keyValuePairs.TryAdd("Married", "0");
            keyValuePairs.TryAdd("ChildrenNumber", "0");
            keyValuePairs.TryAdd("EmergencyContact", fullName);
            keyValuePairs.TryAdd("EmergencyPhone", keyValuePairs["Phone"]);
            keyValuePairs.TryAdd("FamilyNumber", "1");
            keyValuePairs.TryAdd("Education", Education.None.ToString());
            keyValuePairs.TryAdd("WorkingYears", "1");
            keyValuePairs.TryAdd("EnglishLevel", EnglishLevel.None.ToString());
            keyValuePairs.TryAdd("Trainee", "0");
            keyValuePairs.TryAdd("JobDuty", "总经理");
            keyValuePairs.TryAdd("JobTitle", "总经理");
            keyValuePairs.TryAdd("JobDutyKey", "SUB" + companyId + "-000001");
            keyValuePairs.TryAdd("JobTitleKey", "SUB" + companyId + "-000001");
            keyValuePairs.TryAdd("JobLevel", "1");
            keyValuePairs.TryAdd("EmployedDate", DateTime.Now.ToString());
            keyValuePairs.TryAdd("EnglishReadLevel", "1");
            keyValuePairs.TryAdd("EnglishWriteLevel", "1");
            keyValuePairs.TryAdd("EnglishConversationLevel", "1");
            keyValuePairs.TryAdd("Salary", "0");
            keyValuePairs.TryAdd("FullTime", "1");
            keyValuePairs.TryAdd("SalaryCard", "0000-0000-0000-0000-0000");
            keyValuePairs.TryAdd("MaternityLeave", "0");
            keyValuePairs.TryAdd("AnnualLeave", "0");
            keyValuePairs.TryAdd("SurplusAnnualLeave", "0");
            return keyValuePairs;
        }

        private static Dictionary<string, string> GetCompanyInfo(IEnumerable<WorkflowActivityStepSpecificFormItemDto> companyInfoList, string companyName, long editerId, string editer)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            foreach (var item in companyInfoList)
            {
                keyValuePairs.TryAdd(item.BoundField, item.ItemValue);
            }
            if (!string.IsNullOrWhiteSpace(companyName))
            {
                keyValuePairs.TryAdd("CompanySubName", Pinyin.GetInitials(companyName));
            }
            else
            {
                keyValuePairs.TryAdd("CompanySubName", "");
            }
            var businessType = companyInfoList.Where(p => p.BoundField == "BusinessType").FirstOrDefault().ItemValue;
            if (!string.IsNullOrWhiteSpace(businessType))
            {
                keyValuePairs.TryAdd("BusinessTypeName", ((CompanyBusinessType)Enum.Parse(typeof(CompanyBusinessType), businessType)).GetDescriptionString());
            }
            else
            {
                keyValuePairs.TryAdd("BusinessTypeName", "");
            }
            keyValuePairs.TryAdd("CompanyAdminId", "0");
            //删除CompanyAdminName键，表里是AdminFullName字段
            keyValuePairs.Remove("CompanyAdminName");
            keyValuePairs.TryAdd("AdminFullName", companyInfoList.FirstOrDefault(p => p.BoundField == "CompanyAdminName").ItemValue);
            keyValuePairs.TryAdd("StaffCount", "1");
            keyValuePairs.TryAdd("EditerId", editerId.ToString());
            keyValuePairs.TryAdd("Editer", editer);
            return keyValuePairs;
        }

        private static void Log(string message)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(Directory.GetCurrentDirectory());

            FileInfo fileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, "TMSWorkflowConsoleError_SpecificForm", DateTime.Now.ToString("yyyy-MM-dd") + ".txt").ToString());

            if (!Directory.Exists(Path.Combine(directoryInfo.FullName, "TMSWorkflowConsoleError_SpecificForm")))
            {
                Directory.CreateDirectory(Path.Combine(directoryInfo.FullName, "TMSWorkflowConsoleError_SpecificForm"));
            }

            try
            {
                if (!fileInfo.Exists)
                {
                    using (StreamWriter sw = fileInfo.CreateText())
                    {
                        sw.WriteLine("*****************************************");
                        sw.WriteLine("当前时间：{0}", DateTime.Now.ToString());

                        sw.WriteLine("{0}", message);

                        sw.WriteLine();
                    }
                }
                else
                {
                    using (StreamWriter sw = fileInfo.AppendText())
                    {
                        sw.WriteLine("*****************************************");
                        sw.WriteLine("当前时间：{0}", DateTime.Now.ToString());

                        sw.WriteLine("{0}", message);

                        sw.WriteLine();
                    }
                }
            }
            catch (Exception e)
            {
                using (StreamWriter sw = fileInfo.AppendText())
                {
                    sw.WriteLine("*****************************************");
                    sw.WriteLine("当前时间：{0}", DateTime.Now.ToString());
                    sw.WriteLine("构建失败:");
                    sw.WriteLine("{0}", message);

                }
            }
        }
    }
}
